package geektime.io.nio2;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 异步io实现的服务端
 */
public class AsyncSocketServer {
    public static void main(String[] args) {
        // 创建一个异步服务端通道
        try(AsynchronousServerSocketChannel server = AsynchronousServerSocketChannel.open()) {
            // 绑定ip和端口
            server.bind(new InetSocketAddress("localhost", 1234));
            // 创建一个接收客户端连接的事件
            Future<AsynchronousSocketChannel> acceptCon = server.accept();
            //  阻塞等待客户端连接，连接成功后获取到客户端异步通道，超时时间为10秒
            AsynchronousSocketChannel client = acceptCon.get(10, TimeUnit.SECONDS);
            // 如果client不为空，且client处于打开状态
            if (client != null && client.isOpen()) {
                // 从client中读取数据
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                Future<Integer> readFuture = client.read(buffer);
                System.out.println("Receiving msg from client...");
                readFuture.get();
                System.out.println("Received msg from client: " + getCurrentMessage(buffer));
                // 向client写回数据
                buffer.clear();
                String respMsg = "I am fine, thank you! And you?";
                buffer.put(respMsg.getBytes());
                buffer.flip();
                Future<Integer> writeFuture = client.write(buffer);
                System.out.println("Responding to client...");
                writeFuture.get();
                System.out.println("responded to client: " + respMsg);
                // 将buffer清空，为下一次做准备
                buffer.clear();
            }
            // 5分钟后关闭client
            TimeUnit.SECONDS.sleep(5);
            client.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (TimeoutException e) {
            e.printStackTrace();
        }
    }

    public static String getCurrentMessage(ByteBuffer buffer) {
        byte[] bytes = new byte[buffer.position()];
        int i = 0;
        buffer.flip();
        while (buffer.hasRemaining()) {
            bytes[i++] = buffer.get();
        }
        return new String(bytes);
    }
}
